package service;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;


/**
 * Created by fanzhenyu02 on 2020/7/23.
 * count English article word frequency and return top 10 word.
 */
public class WordCountService {

    public long startTime = System.currentTimeMillis();

    /**
     * read from file.
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public String readText(String fileName) throws IOException {
        //loda data.
        BufferedReader reader = new BufferedReader(new FileReader(fileName));
        String line;
        StringBuffer stringBuffer = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            if (line.trim() != "") {
                stringBuffer.append(line);
            }
        }
        return stringBuffer.toString();
    }

    /**
     * split text by white space.
     *
     * @param string
     * @param re
     * @return
     */
    public String[] splitText(String string, String re) {
        return string.split(re);
    }

    /**
     * count word frequency.
     *
     * @param words
     * @return
     */
    public Map<String, Integer> countWord(String[] words) {
        Map<String, Integer> count = new HashMap<>();
        Integer num;
        for (String word : words) {
            num = count.get(word);
            if (num == null) {
                num = 1;
            } else {
                num++;
            }
            count.put(word, num);
        }
        return count;
    }

    /**
     * The word is sorted according to the frequency of occurrence.
     * By default, it is in ascending order
     *
     * @param words
     * @param reverse
     * @return
     */
    public Map<String, Integer> sortRate(Map<String, Integer> words, boolean reverse) {
        List<Map.Entry<String, Integer>> list = new ArrayList<>(words.entrySet());

        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                if (reverse) {
                    return o2.getValue() - o1.getValue();
                } else {
                    return o1.getValue() - o2.getValue();
                }
            }
        });

        Map<String, Integer> result = new LinkedHashMap<>();
        for (Map.Entry<String, Integer> map : list) {
            result.put(map.getKey(), map.getValue());
        }
        return result;
    }

    /**
     * print top word.
     *
     * @param wordRate
     * @param topCount
     */
    public void printTopWord(Map<String, Integer> wordRate, int topCount) {
        int count = 1;
        for (String s : wordRate.keySet()) {
            System.out.println(s + ":" + wordRate.get(s));
            if (++count > topCount) break;
        }
    }

    public static void main(String[] args) throws IOException {
        WordCountService an = new WordCountService();

        //step 1:read form disk.
        String text = an.readText("/Users/vonmax/Downloads/test.txt");

        //step 2:split the content.
        String[] words = an.splitText(text, " ");

        //step 3:do frequencey count.
        Map<String, Integer> count = an.countWord(words);

        //step 4:sory the chooseMap by frequeney.
        Map<String, Integer> wordRate = an.sortRate(count, true);

        // print result
        an.printTopWord(wordRate, 10); //specify top 10.

        System.out.println("\ntotal time consume: " + (System.currentTimeMillis() - an.startTime) + " ms.");
    }
}


